using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Gko.Utils
{
	public abstract class TaskBase : DisposableBase, ITask
	{
		private readonly AutoResetEvent resumeEvent;
		private ProceedResult resumeResult;

		protected TaskBase(string name, int priority)
			: this(name, priority, null)
		{
		}

		protected TaskBase(string name, int priority, Func<ProceedResult, ProceedResult> complete)
		{
			this.CompleteFunc = complete;
			this.Name = name;
			this.Priority = priority;
			this.resumeEvent = new AutoResetEvent(false);
			this.AddDisposed(this.resumeEvent);
		}

		private Func<ProceedResult, ProceedResult> CompleteFunc
		{
			get;
			set;
		}

		public string Name
		{
			get;
			private set;
		}

		public int Priority
		{
			get;
			private set;
		}

		public abstract ProceedResult Proceed();

		public ProceedResult WaitForResume()
		{
			this.resumeEvent.Reset();
			this.resumeEvent.WaitOne();
			return this.resumeResult;
		}

		public void ResumeTask(ProceedResult result)
		{
			this.resumeResult = result;
			this.resumeEvent.Set();
		}

		public ProceedResult OnProceed()
		{
			return this.OnComplete(this.Proceed());
		}

		public event EventHandler<TaskCompletedEventArgs> Completed;
	
		private ProceedResult OnComplete(ProceedResult proceedResult)
		{
			if (this.CompleteFunc != null) {
				proceedResult = this.CompleteFunc(proceedResult);
			}
			if (this.Completed != null) {
				var e = new TaskCompletedEventArgs(proceedResult);
				this.Completed(this, e);
				proceedResult = e.ProceedResult;
			}
			return proceedResult;
		}
	}
}